package comic

import (
	"comic/internal/logic/book"
	"comic/internal/pb"
	"common"
	"common/auth"
	"common/logic"
	"common/zapx"
	"context"
	"errors"
	"models/consts"
	"models/dal/model"
	"models/dal/query"
	"strings"
	"time"

	"go.uber.org/zap"
	"gorm.io/gen"
)

type ComicLogic struct {
	logic.BasePageLogic
}

// NewComicLogic 创建漫画查询
func NewComicLogic() ComicLogic {
	l := ComicLogic{
		logic.BasePageLogic{
			Page:     0,
			PerPage:  15,
			NextPage: 0,
			Total:    0,
		},
	}
	return l
}

// GetList 获取列表
func (cl *ComicLogic) GetList(title *string, navigateId *int64) (ret []*pb.ComicEntity) {
	//查询条件
	ctx, cancel := common.WithTimeoutContext(time.Second * 2)
	defer cancel()
	comicModel := query.Q.FaComic.WithContext(ctx)
	var wheres []gen.Condition
	if title != nil {
		wheres = append(wheres, comicModel.Where(query.Q.FaComic.Title.Like("%"+*title+"%")))
		IncrHotSearchNum(*title)
	}
	if navigateId != nil {
		wheres = append(wheres, comicModel.Where(query.Q.FaComic.NavigateID.Eq(int32(*navigateId))))
	}
	//查询漫画
	r, total, err := comicModel.Where(wheres...).Order(query.Q.FaComic.ID.Desc()).FindByPage(cl.GetOffset(), int(cl.GetPerPage()))
	if err != nil {
		zapx.Logger.Error("[GetList]查询数据失败", zap.Error(err))
		return
	}
	cl.Total = total
	for _, comic := range r {
		//查询封面
		var swiperArr []string
		swiper := strings.Split(comic.Swiper, ",")
		for _, s := range swiper {
			swiperArr = append(swiperArr, common.ParseUri(s))
		}
		ret = append(ret, &pb.ComicEntity{
			Id:     comic.ID,
			Title:  comic.Title,
			Thumb:  common.ParseUri(comic.Thumb),
			Swiper: swiperArr,
			Author: comic.Author,
			Intro:  comic.Intro,
			Tags:   strings.Split(comic.Tags, ","),
		})
	}
	return
}

// GetChapterListByComicId 根据漫画 id 获取章节列表
func (cl *ComicLogic) GetChapterListByComicId(comicId int32) (ret []*pb.ChapterEntity) {
	ctx, cancel := common.WithTimeoutContext(time.Second * 2)
	defer cancel()
	chapterModel := query.Q.FaChapter.WithContext(ctx)
	var wheres = []gen.Condition{
		chapterModel.Where(query.Q.FaChapter.ComicID.Eq(comicId)),
	}
	list, currentTotal, err := chapterModel.
		Where(wheres...).
		Order(query.Q.FaChapter.CreatedAt.Asc()).
		FindByPage(int(cl.Page*cl.PerPage), int(cl.PerPage))
	if err != nil {
		zapx.Logger.Error("[GetChapterListByComicId]查询漫画章节失败", zap.Error(err))
		return
	}
	cl.SetTotal(currentTotal)
	for _, chapter := range list {
		ret = append(ret, &pb.ChapterEntity{
			Id:      chapter.ID,
			Title:   chapter.Title,
			Thumb:   common.ParseUri(chapter.Thumb),
			Intro:   chapter.Intro,
			ComicId: chapter.ComicID,
			IsVip:   chapter.IsVip,
		})
	}
	return
}

// GetPageInfo 获取页码信息
func (cl *ComicLogic) GetPageInfo() *pb.Page {
	return &pb.Page{
		CurrentPage: cl.GetCurrentPage(),
		NextPage:    cl.GetNextPage(),
		Total:       cl.GetTotal(),
		PerPage:     cl.GetPerPage(),
	}
}

// GetResourceByChapterId 根据章节id获取漫画图片
func GetResourceByChapterId(grpcCtx context.Context, chapterId int32) (ret []string, err error) {
	ret = []string{}
	ctx, cancel := common.WithTimeoutContext(time.Second * 2)
	defer cancel()
	chapterModel := query.Q.FaChapter.WithContext(ctx)
	chapter, err := chapterModel.Where(query.Q.FaChapter.ID.Eq(chapterId)).First()
	if err != nil {
		return []string{}, errors.New("章节不存在")
	}
	if chapter.IsVip == consts.CHAPTER_IS_VIP {
		user, err := common.GetUserByGrpc(grpcCtx)
		if err != nil {
			return []string{}, err
		}
		if common.GetUserVip(user) <= 0 {
			return []string{}, errors.New("请先升级vip")
		}
	}
	resourceModel := query.Q.FaChapterSource.WithContext(ctx)
	list, err := resourceModel.Where(query.Q.FaChapterSource.ChapterID.Eq(chapterId)).Find()
	if err != nil {
		zapx.Logger.Error("[GetResourceByChapterId]查询漫画章节资源失败", zap.Error(err))
		return
	}
	for _, source := range list {
		ret = append(ret, common.ParseUri(source.Source))
	}
	return
}

// GetComicDetail 获取漫画详情信息
func (cl *ComicLogic) GetComicDetail(grpcCtx context.Context, comicId int32) (*pb.ComicEntity, error) {
	ctx, cancel := common.WithTimeoutContext(time.Second * 2)
	defer cancel()
	comicModel := query.Q.FaComic.WithContext(ctx)
	raw, err := comicModel.Where(query.Q.FaComic.ID.Eq(comicId)).First()
	if err != nil {
		zapx.Logger.Error("[GetComicDetail]查询漫画详情失败", zap.Error(err))
		return nil, errors.New("查询漫画失败")
	}
	var incViewNumChan = make(chan struct{})
	//增加阅读数量
	go IncrComicViewNum(raw, incViewNumChan)
	//获取完整的封面
	fullThumb := common.ParseUri(raw.Thumb)

	var swiperList = make([]string, 0)

	s := strings.Split(raw.Swiper, ",")

	//循环获取完整路径
	for _, s2 := range s {
		swiperList = append(swiperList, common.ParseUri(s2))
	}

	var isFavourite int32 = 0

	_, err = common.GetUserByGrpc(grpcCtx)
	if err == nil {
		isFavourite = book.IsFavourite(grpcCtx, comicId)
	}

	<-incViewNumChan
	return &pb.ComicEntity{
		Id:          raw.ID,
		Title:       raw.Title,
		Thumb:       fullThumb,
		Swiper:      swiperList,
		Author:      raw.Author,
		Intro:       raw.Intro,
		IsFavourite: isFavourite,
	}, nil
}

// ChapterDetail 章节详情
func ChapterDetail(grpcCtx context.Context, chapterId int32) (*pb.GetChapterDetailResponse, error) {
	ctx, cancel := common.WithTimeoutContext(time.Second * 2)
	defer cancel()

	chapterModel := query.Q.FaChapter.WithContext(ctx)
	chapter, err := chapterModel.Where(query.Q.FaChapter.ID.Eq(chapterId)).First()
	if err != nil {
		return nil, err
	}
	//判断是否需要vip
	if chapter.IsVip == consts.CHAPTER_IS_VIP {
		user, err := common.GetUserByGrpc(grpcCtx)
		if err != nil {
			return nil, err
		}
		vip := common.GetUserVip(user)
		if vip <= 0 {
			return nil, errors.New("请先升级会员等级")
		}
	}
	return &pb.GetChapterDetailResponse{
		ChapterDetail: &pb.ChapterEntity{
			Id:      chapter.ID,
			Title:   chapter.Title,
			Thumb:   common.ParseUri(chapter.Thumb),
			Intro:   chapter.Intro,
			ComicId: chapter.ComicID,
		},
	}, nil
}

// IncrComicViewNum 增加漫画阅读量
func IncrComicViewNum(raw *model.FaComic, c chan struct{}) {
	defer func() {
		c <- struct{}{}
	}()
	ctx, cancel := common.WithTimeoutContext(time.Second * 2)
	defer cancel()
	query.FaComic.WithContext(ctx).Where(query.FaComic.ID.Eq(raw.ID)).UpdateSimple(query.Q.FaComic.ViewNum.Add(1))
}

// Find 帮找漫画
func (cl *ComicLogic) Find(auth *auth.AuthObject, title string, link *string) error {
	user := auth.GetCurrentUser()
	ctx, cancel := common.WithTimeoutContext(time.Second * 2)
	defer cancel()
	comicLookForModel := query.Q.FaComicLookFor.WithContext(ctx)
	cnt, _ := comicLookForModel.Where(query.Q.FaComicLookFor.Title.Eq(title)).Count()
	if cnt > 0 {
		return errors.New("帮找的漫画已经存在了,请等待上架")
	}
	l := ""
	if link != nil {
		l = *link
	}
	err := comicLookForModel.Create(&model.FaComicLookFor{
		UserID: user.ID,
		Title:  title,
		Link:   l,
	})
	if err != nil {
		zapx.Logger.Error("comicLookForModel insert fail", zap.Error(err))
		return errors.New("系统错误")
	}
	return nil
}
